
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
#region Copyright and License
/*
Copyright 2003 Jason Alexander, nGallery.org
Design work copyright Thomas Johansen (http://www.aylarsolutions.com/)

GOTDOTNET WORKSPACES COMMERCIAL DERIVATIVES LICENSE
Copyright (C) 2003 Microsoft Corporation

You can use this Software for any commercial or noncommercial purpose, 
including distributing derivative works.

In return, we simply require that you agree:

1. Not to remove any copyright notices from the Software. 
2. That if you distribute the Software in source code form you do so only 
   under this License (i.e. you must include a complete copy of this License 
   with your distribution), and if you distribute the Software solely in 
   object form you only do so under a license that complies with this License. 
3. That the Software comes "as is", with no warranties. None whatsoever. This 
   means no express, implied or statutory warranty, including without 
   limitation, warranties of merchantability or fitness for a particular 
   purpose or any warranty of noninfringement. Also, you must pass this 
   disclaimer on whenever you distribute the Software.
4. That neither Microsoft nor any contributor to the Software will be liable 
   for any of those types of damages known as indirect, special, consequential, 
   or incidental related to the Software or this License, to the maximum extent 
   the law permits, no matter what legal theory it�s based on. Also, you must 
   pass this limitation of liability on whenever you distribute the Software.
5. That if you sue anyone over patents that you think may apply to the 
   Software for a person's use of the Software, your license to the Software 
   ends automatically. 
6. That the patent rights, if any, licensed hereunder only apply to the 
   Software, not to any derivative works you make. 
7. That your rights under this License end automatically if you breach it in 
   any way.
*/
#endregion

// Parts of this code were borrowed from vbAccelerator.com.
// vbAccelerator's Copyright Notice:
// This product includes software developed by vbAccelerator (http://vbaccelerator.com/).
// Version 1.0
// Copyright (c) 2002 vbAccelerator.com

using System;
using System.Drawing;
using System.Runtime.InteropServices;

namespace MediaCache
{

	/// <summary>
	/// Provides access to information embedded in image files.
	/// </summary>
	[Serializable]
	public class EXIF 
	{
        protected int _ID;
        protected DateTime _createDate;
        protected string _name;
        protected Image _picture = null;
		
		#region -- Constructors --
			/// <summary>
			/// This is base constructor of the EXIF class.
			/// </summary>
        public EXIF(){}
        public EXIF(Image img) { _picture = img; }
		#endregion
        /// <summary>
        /// 
        /// </summary>
        public Image Picture
        {
            get { return _picture; }
            set { _picture = value; }
        }
		#region -- Public methods --
			/// <summary>
			/// This method returns EXIF property values.
			/// </summary>
			/// <param name="exifCode">EXIF property to be returned.</param>
			public string GetEXIFProperty(exifCode exifCode)
			{
				// Declare local variables.
				string returnValue="";
				if(_picture!=null)
				    try
				    {
					    // All of the EXIF properties will return strings to display in the control.
					    // Some of the properties require additional formatting or massaging
					    // of the data once it is returned. Those properties have their own
					    // methods.
					    switch(exifCode)
					    {
						    case exifCode.ImageDescription:
							    returnValue = ParsedString(exifCode.ImageDescription);
							    break;
						    case exifCode.Make:
							    returnValue = ParsedString(exifCode.Make);
							    break;
						    case exifCode.Model:
							    returnValue = ParsedString(exifCode.Model);
							    break;
						    case exifCode.Orientation:
							    returnValue = Orientation();
							    break;
						    case exifCode.XResolution:
							    returnValue = ParseResolution(exifCode.XResolution);
							    break;
						    case exifCode.YResolution:
							    returnValue = ParseResolution(exifCode.YResolution);
							    break;
						    case exifCode.ResolutionUnit:
							    returnValue = ResolutionUnit();
							    break;
						    case exifCode.Software:
							    returnValue = ParsedString(exifCode.Software);
							    break;
						    case exifCode.DateTime:
							    returnValue = ParsedDate(exifCode.DateTime).ToString();
							    break;
						    case exifCode.WhitePoint:
							    returnValue = WhitePoint();
							    break;
						    case exifCode.PrimaryChromaticities:
							    returnValue = PrimaryChromaticities();
							    break;
						    case exifCode.YCbCrCoefficients:
							    returnValue = YCbCrCoefficients();
							    break;
						    case exifCode.YCbCrPositioning:
							    returnValue = YCbCrPositioning();
							    break;
						    case exifCode.ReferenceBlackWhite:
							    returnValue = ReferenceBlackWhite();
							    break;
						    case exifCode.Copyright:
							    returnValue = ParsedString(exifCode.Copyright);
							    break;
						    case exifCode.ExposureTime:
							    returnValue = ExposureTime();
							    break;
						    case exifCode.FNumber:
							    returnValue = FNumber();
							    break;
						    case exifCode.ExposureProgram:
							    returnValue = ExposureProgram();
							    break;
						    case exifCode.ISOSpeedRatings:
							    returnValue = UnformattedShort(exifCode.ISOSpeedRatings);
							    break;
						    case exifCode.ExifVersion:
							    returnValue = ParsedString(exifCode.ExifVersion);
							    break;
						    case exifCode.DateTimeOriginal:
							    returnValue = ParsedDate(exifCode.DateTimeOriginal).ToString();
							    break;
						    case exifCode.DateTimeDigitized:
							    returnValue = ParsedDate(exifCode.DateTimeDigitized).ToString();
							    break;
						    case exifCode.ComponentsConfiguration:
							    returnValue = ComponentsConfiguration();
							    break;
						    case exifCode.CompressedBitsPerPixel:
							    returnValue = CompressedBitsPerPixel();
							    break;
						    case exifCode.ShutterSpeedValue:
							    returnValue = ShutterSpeedValue();
							    break;
						    case exifCode.ApertureValue:
							    returnValue = ApertureValue();
							    break;
						    case exifCode.BrightnessValue:
							    returnValue = BrightnessValue();
							    break;
						    case exifCode.ExposureBiasValue:
							    returnValue = ExposureBiasValue();
							    break;
						    case exifCode.MaxApertureValue:
							    returnValue = MaxApertureValue();
							    break;
						    case exifCode.SubjectDistance:
							    returnValue = SubjectDistance();
							    break;
						    case exifCode.MeteringMode:
							    returnValue = MeteringMode();
							    break;
						    case exifCode.LightSource:
							    returnValue = LightSource();
							    break;
						    case exifCode.Flash:
							    returnValue = Flash();
							    break;
						    case exifCode.FocalLength:
							    returnValue = FocalLength();
							    break;
						    case exifCode.MakerNote:
							    returnValue = MakerNote();
							    break;
						    case exifCode.UserComment:
							    returnValue = ParsedString(exifCode.UserComment);
							    break;
						    case exifCode.SubsecTime:
							    returnValue = ParsedString(exifCode.SubsecTime);
							    break;
						    case exifCode.SubsecTimeOriginal:
							    returnValue = ParsedString(exifCode.SubsecTimeOriginal);
							    break;
						    case exifCode.SubsecTimeDigitized:
							    returnValue = ParsedString(exifCode.SubsecTimeDigitized);
							    break;
						    case exifCode.FlashpixVersion:
							    returnValue = ParsedString(exifCode.FlashpixVersion);
							    break;
						    case exifCode.ColorSpace:
							    returnValue = ColorSpace();
							    break;
						    case exifCode.RelatedSoundFile:
							    returnValue = ParsedString(exifCode.RelatedSoundFile);
							    break;
						    case exifCode.FocalPlaneXResolution:
							    returnValue = FocalPlaneXResolution();
							    break;
						    case exifCode.FocalPlaneYResolution:
							    returnValue = FocalPlaneYResolution();
							    break;
						    case exifCode.FocalPlaneResolutionUnit:
							    returnValue = ResolutionUnit();
							    break;
						    case exifCode.ExposureIndex:
							    returnValue = ExposureIndex();
							    break;
						    case exifCode.SensingMethod:
							    returnValue = SensingMethod();
							    break;
						    case exifCode.FileSource:
							    returnValue = FileSource();
							    break;
						    case exifCode.SceneType:
							    returnValue = SceneType();
							    break;
						    case exifCode.CFAPattern:
							    returnValue = ParsedString(exifCode.CFAPattern);
							    break;
						    case exifCode.InteroperabilityIndex:
							    returnValue = ParsedString(exifCode.InteroperabilityIndex);
							    break;
						    case exifCode.ImageWidth:
							    returnValue = UnformattedShort(exifCode.ImageWidth);
							    break;
						    case exifCode.ImageLength:
							    returnValue = UnformattedShort(exifCode.ImageLength);;
							    break;
						    case exifCode.BitsPerSample:
							    returnValue = BitsPerSample();
							    break;
						    case exifCode.Compression:
							    returnValue = Compression();
							    break;
						    case exifCode.PhotometricInterpretation:
							    returnValue = PhotometricInterpretation();
							    break;
						    case exifCode.StripOffsets:
							    returnValue = StripOffsets();
							    break;
						    case exifCode.SamplesPerPixel:
							    returnValue = UnformattedShort(exifCode.SamplesPerPixel);
							    break;
						    case exifCode.RowsPerStrip:
							    returnValue = UnformattedShort(exifCode.RowsPerStrip);
							    break;
						    case exifCode.StripByteCounts:
							    returnValue = StripByteCounts();
							    break;
						    case exifCode.PlanarConfiguration:
							    returnValue = PlanarConfiguration();
							    break;
						    case exifCode.YCbCrSubSampling:
							    returnValue = YCbCrSubSampling();
							    break;
						    case exifCode.ImageUniqueID:
							    returnValue = ParsedString(exifCode.ImageUniqueID);
							    break;
						    case exifCode.JPEGInterchangeFormatLength:
							    returnValue = UnformattedShort(exifCode.JPEGInterchangeFormatLength);
							    break;
						    case exifCode.TransferFunction:
							    returnValue = "Not implemented.";
							    break;
						    case exifCode.PixelXDimension:
							    returnValue = UnformattedShort(exifCode.PixelXDimension);
							    break;
						    case exifCode.PixelYDimension:
							    returnValue = UnformattedShort(exifCode.PixelYDimension);
							    break;
						    case exifCode.SpectralSensitivity:
							    returnValue = ParsedString(exifCode.SpectralSensitivity);
							    break;
						    case exifCode.OECF:
							    returnValue = ParsedString(exifCode.OECF);
							    break;
						    case exifCode.CustomRendered:
							    returnValue = CustomRendered();
							    break;
						    case exifCode.ExposureMode:
							    returnValue = ExposureMode();
							    break;
						    case exifCode.WhiteBalance:
							    returnValue = WhiteBalance();
							    break;
						    case exifCode.DigitalZoomRatio:
							    returnValue = DigitalZoomRatio();
							    break;
						    case exifCode.FocalLengthIn35mmFilm:
							    returnValue = FocalLengthIn35mmFilm();
							    break;
						    case exifCode.SceneCaptureType:
							    returnValue = SceneCaptureType();
							    break;
						    case exifCode.GainControl:
							    returnValue = GainControl();
							    break;
						    case exifCode.Contrast:
							    returnValue = Contrast();
							    break;
						    case exifCode.Saturation:
							    returnValue = Saturation();
							    break;
						    case exifCode.Sharpness:
							    returnValue = Sharpness();
							    break;
						    case exifCode.DeviceSettingDescription:
							    returnValue = ParsedString(exifCode.DeviceSettingDescription);
							    break;
						    case exifCode.SubjectDistanceRange:
							    returnValue = SubjectDistanceRange();
							    break;
						    default:
							    returnValue = "EXIF property not found.";
							    break;
					    }

					    
				    }
				    catch
				    {
				    }
                return returnValue;
			}
		#endregion

		#region -- EXIF Methods --
						
			/// <summary>
			/// This method returns the bits per sample EXIF property.
			/// </summary>
			private string BitsPerSample()
			{
				//Declare local variables.
				string returnValue = "EXIF property not found.";
				byte[] data = GetPropertyValue(exifCode.BitsPerSample);

				//Translate the EXIF code into a readable value.
				if (!data.Equals(null))
					returnValue = data[0].ToString() + " " + data[1].ToString() + " " + data[2].ToString();

				return returnValue;
			} 

			/// <summary>
			/// This method returns the compression EXIF property.
			/// </summary>
			private string Compression()
			{
				//Declare local variables.
				string returnValue = "EXIF property not found.";
				byte[] data = GetPropertyValue(exifCode.Compression);

				//Translate the EXIF code into a readable value.
				if (!data.Equals(null))
					switch(data[0])
					{
						case 1:
							returnValue = "uncompressed";
							break;
						case 6:
							returnValue ="JPEG compression (thumbnails only)";
							break;
						default:
							returnValue = "reserved";
							break;
					}
			
				return returnValue;
			} 

			/// <summary>
			/// This method returns the photometric interpretation EXIF property.
			/// </summary>
			private string PhotometricInterpretation()
			{
				//Declare local variables.
				string returnValue = "EXIF property not found.";
				byte[] data = GetPropertyValue(exifCode.PhotometricInterpretation);

				//Translate the EXIF code into a readable value.
				if (data != null)
					switch(data[0])
					{
						case 2:
							returnValue = "RBG";
							break;
						case 6:
							returnValue ="YCbCr";
							break;
						default:
							returnValue = "reserved";
							break;
					}
			
				return returnValue;
			} 

			/// <summary>
			/// This method returns the strip offsets EXIF property.
			/// </summary>
			private string StripOffsets()
			{
				return "Not implemented.";
			} 
			
			/// <summary>
			/// This method returns the strip byte counts EXIF property.
			/// </summary>
			private string StripByteCounts()
			{
				return "Not implemented.";
			} 

			/// <summary>
			/// This method returns the planar configuration EXIF property.
			/// </summary>
			private string PlanarConfiguration()
			{
				//Declare local variables.
				string returnValue = "EXIF property not found.";
				byte[] data = GetPropertyValue(exifCode.PlanarConfiguration);

				//Translate the EXIF code into a readable value.
				if (data != null)
					switch(data[0])
					{
						case 1:
							returnValue = "chunky format";
							break;
						case 2:
							returnValue ="planar format";
							break;
						default:
							returnValue = "reserved";
							break;
					}
			
				return returnValue;
			} 
			
			/// <summary>
			/// This method returns the YCbCr subsampling EXIF property.
			/// </summary>
			private string YCbCrSubSampling()
			{
				//Declare local variables.
				string returnValue = "EXIF property not found.";
				byte[] data = GetPropertyValue(exifCode.YCbCrSubSampling);

				//Translate the EXIF code into a readable value.
				if (data != null)
					switch(data[0])
					{
						case 2:
							if(data[1] == 1)
							{
								returnValue = "YCbCr4:2:2";
							}
							else
							{
								returnValue = "YCbCr4:2:0";
							}
							
							break;
						default:
							returnValue = "reserved";
							break;
					}
			
				return returnValue;
			} 
		
			/// <summary>
			/// This method returns the orientation EXIF property.
			/// </summary>
			private string Orientation()
			{
				//Declare local variables.
				string returnValue = "EXIF property not found.";
				byte[] data = GetPropertyValue(exifCode.Orientation);

				//Translate the EXIF code into a readable value.
				if (data.Length > 0)
					switch (data[0])
					{
						case 1:
							returnValue = "The 0th row is at the visual top of the image, and the 0th column is the visual left-hand side.";
							break;
						case 2:
							returnValue = "The 0th row is at the visual top of the image, and the 0th column is the visual right-hand side.";
							break;
						case 3:
							returnValue = "The 0th row is at the visual bottom of the image, and the 0th column is the visual right-hand side.";
							break;
						case 4:
							returnValue = "The 0th row is at the visual bottom of the image, and the 0th column is the visual left-hand side.";
							break;
						case 5:
							returnValue = "The 0th row is at the visual left-hand side of the image, and the 0th column is the visual top.";
							break;
						case 6:
							returnValue = "The 0th row is at the visual right-hand side of the image, and the 0th column is the visual top.";
							break;
						case 7:
							returnValue = "The 0th row is at the visual right-hand side of the image, and the 0th column is the visual bottom.";
							break;
						case 8:
							returnValue = "The 0th row is at the visual left-hand side of the image, and the 0th column is the visual bottom.";
							break;
						default:
							returnValue = "Other";
							break;
					}
				
				return returnValue;
			} 

			/// <summary>
			/// This method returns the resolution unit EXIF property.
			/// </summary>
			private string ResolutionUnit()
			{
				//Declare local variables.
				string returnValue = "EXIF property not found.";
				byte[] resUnit = GetPropertyValue(exifCode.ResolutionUnit);

				//Translate the EXIF code into a readable value.
				if (resUnit != null)
					switch(resUnit[0])
					{
						case 2:
							returnValue = "inches";
							break;
						case 3:
							returnValue ="centimeters";
							break;
						default:
							returnValue = "reserved";
							break;
					}
		
				return returnValue;
			} 

			/// <summary>
			/// This method returns the white point EXIF property.
			/// </summary>
			private string WhitePoint()
			{
				string returnValue = "EXIF property not found.";
				EXIFRational[] data = ParsedRationalArray(exifCode.WhitePoint);

				if(data.Length > 0)
					returnValue = data[0].Denominator.ToString() + ", " + data[1].Denominator.ToString();
					
				return returnValue;
			} 

			/// <summary>
			/// This method returns the primary chromaticities EXIF property.
			/// </summary>
			private string PrimaryChromaticities()
			{
				string returnValue = "EXIF property not found.";
				EXIFRational[] data = ParsedRationalArray(exifCode.PrimaryChromaticities);

				if(data.Length > 0)
					returnValue = data[0].Denominator.ToString() + ", " + data[1].Denominator.ToString() + ", "
								        + data[2].Denominator.ToString() + ", " + data[3].Denominator.ToString() + ", "
								        + data[4].Denominator.ToString() + ", " + data[5].Denominator.ToString();
					
				return returnValue;
			} 

			/// <summary>
			/// This method returns the YCbCr coefficients EXIF property.
			/// </summary>
			private string YCbCrCoefficients()
			{
				string returnValue = "EXIF property not found.";
				EXIFRational[] data = ParsedRationalArray(exifCode.YCbCrCoefficients);

				if(data.Length > 0)
					returnValue = data[0].Denominator.ToString() + ", " + data[1].Denominator.ToString() + ", " + data[2].Denominator.ToString();
					
				return returnValue;
			} 

			/// <summary>
			/// This method returns the YCbCr positioning EXIF property.
			/// </summary>
			private string YCbCrPositioning()
			{
				//Declare local variables.
				string returnValue = "";
				byte[] data = GetPropertyValue(exifCode.YCbCrPositioning);

				//Translate the EXIF code into a readable value.
				if (data.Length > 0)
				{
					switch(data[0])
					{
						case 1:
							returnValue = "centered";
							break;
						case 2:
							returnValue ="co-sited";
							break;
						default:
							returnValue = "reserved";
							break;
					}
				}
				else
					returnValue = "EXIF property not found.";

				return returnValue;
			} 

			/// <summary>
			/// This method returns the reference black white EXIF property.
			/// </summary>
			private string ReferenceBlackWhite()
			{
				string returnValue = "EXIF property not found.";
				EXIFRational[] data = ParsedRationalArray(exifCode.ReferenceBlackWhite);

				if(data.Length > 0)
					returnValue = "[" + data[0].Denominator.ToString() + ", "
						        	            + data[1].Denominator.ToString() + ", "
							                    + data[2].Denominator.ToString() + ", "
							                    + data[3].Denominator.ToString() + ", "
							                    + data[4].Denominator.ToString() + ", "
							                    + data[5].Denominator.ToString() + "]";
					
				return returnValue;
			} 

			/// <summary>
			/// This method returns the exposure time EXIF property.
			/// </summary>
			private string ExposureTime()
			{
				//Declare local variables.
				string returnValue = "EXIF property not found.";
				EXIFRational exposureTime = ParsedRational(exifCode.ExposureTime);

				//Translate the EXIF code into a readable value.
				if (!exposureTime.Equals(null))
				{
					if (exposureTime.Numerator == 0 && exposureTime.Denominator == 0)
					{
						returnValue = "N/A";
					}
					else
					{
						returnValue = string.Format("{0}/{1} s", exposureTime.Numerator, exposureTime.Denominator);
					}
				}
				else
					returnValue = "N/A";
				
				return returnValue;
			} 

			/// <summary>
			/// This method returns the FNumber EXIF property.
			/// </summary>
			private string FNumber()
			{
				//Declare local variables.
				string returnValue = "EXIF property not found.";
				EXIFRational fNumber = ParsedRational(exifCode.FNumber);

				//Translate the EXIF code into a readable value.
				if (!fNumber.Equals(null))
					returnValue = string.Format("f{0}", (float)(fNumber.Numerator/fNumber.Denominator));
				
				return returnValue;
			} 

			/// <summary>
			/// This method returns the exposure program EXIF property.
			/// </summary>
			private string ExposureProgram()
			{
				//Declare local variables.
				string returnValue = "EXIF property not found.";
				byte[] data = GetPropertyValue(exifCode.ExposureProgram);

				//Translate the EXIF code into a readable value.
				if (data.Length > 0)
					switch(data[0])
					{
						case 0:
							returnValue = "Not defined";
							break;
						case 1:
							returnValue = "Manual";
							break;
						case 2:
							returnValue ="Normal program";
							break;
						case 3:
							returnValue ="Aperture priority";
							break;
						case 4:
							returnValue ="Shutter priority";
							break;
						case 5:
							returnValue ="Creative program (biased toward depth of field)";
							break;
						case 6:
							returnValue ="Action program (biased toward fast shutter speed)";
							break;
						case 7:
							returnValue ="Portrait mode (for closeup photos with the background out of focus)";
							break;
						case 8:
							returnValue ="Landscape mode (for landscape photos with the background in focus)";
							break;
						default:
							returnValue = "Reserved";
							break;
					}
				
				return returnValue;
			} 

			/// <summary>
			/// This method returns the components configuration EXIF property.
			/// </summary>
			private string ComponentsConfiguration()
			{
				//Declare local variables.
				string returnValue = "EXIF property not found.";
				byte[] data = GetPropertyValue(exifCode.ComponentsConfiguration);

				switch(data[0])
				{
					case 1:
						returnValue = "YCbCr";
						break;
					case 4:
						returnValue = "RGB";
						break;
					default:
						returnValue = "Reserved";
						break;
				}

				return returnValue;
			} 

			/// <summary>
			/// This method returns the compressed bits per pixel EXIF property.
			/// </summary>
			// This method needs to fixed to return the correct value.
			private string CompressedBitsPerPixel()
			{
				//Declare local variables.
				string returnValue = "EXIF property not found.";
				EXIFRational cbpp = ParsedRational(exifCode.CompressedBitsPerPixel);

				//Translate the EXIF code into a readable value.
				if (!cbpp.Equals(null))
					returnValue = string.Format("{0}/{1}", cbpp.Numerator, cbpp.Denominator);
				
				return returnValue;
			} 

			/// <summary>
			/// This method returns the aperture value EXIF property.
			/// </summary>
			private string ApertureValue()
			{
				//Declare local variables.
				string returnValue = "EXIF property not found.";
				EXIFRational fNumber = ParsedRational(exifCode.FNumber);

				//Translate the EXIF code into a readable value.
				if (!fNumber.Equals(null))
				{
					double av = Math.Round(2 * Math.Log(((fNumber.Numerator/fNumber.Denominator)), 2.00));
					returnValue = string.Format("f{0}", (double) av);
				}
					
				return returnValue;
			} 

			/// <summary>
			/// This method returns the shutter speed value EXIF property.
			/// </summary>
			private string ShutterSpeedValue()
			{
				//Declare local variables.
				string returnValue = "EXIF property not found.";

				returnValue = ExposureTime();
				
				return returnValue;
			} 

			/// <summary>
			/// This method returns the subject distance EXIF property.
			/// </summary>
			private string SubjectDistance()
			{
				//Declare local variables.
				string returnValue = "EXIF property not found.";
				EXIFRational sd = ParsedRational(exifCode.SubjectDistance);

				
				//Translate the EXIF code into a readable value.
				if (!sd.Equals(null))
					returnValue = string.Format("{0}", sd.Numerator);
				
				return returnValue;
			} 

			/// <summary>
			/// This method returns the metering mode EXIF property.
			/// </summary>
			private string MeteringMode()
			{
				//Declare local variables.
				string returnValue = "EXIF property not found.";
				byte[] data = GetPropertyValue(exifCode.MeteringMode);

				//Translate the EXIF code into a readable value.
				if (data.Length > 0)
					switch(data[0])
					{
						case 0:
							returnValue = "Unknown";
							break;
						case 1:
							returnValue = "Average";
							break;
						case 2:
							returnValue ="CenterWeightedAverage";
							break;
						case 3:
							returnValue ="Spot";
							break;
						case 4:
							returnValue ="MultiSpot";
							break;
						case 5:
							returnValue ="Pattern";
							break;
						case 6:
							returnValue ="Partial";
							break;
						case 255:
							returnValue ="Other";
							break;
						default:
							returnValue = "Reserved";
							break;
					}
				
				return returnValue;		
			} 

			/// <summary>
			/// This method returns the light source EXIF property.
			/// </summary>
			private string LightSource()
			{
				//Declare local variables.
				string returnValue = "EXIF property not found.";
				byte[] data = GetPropertyValue(exifCode.LightSource);

				//Translate the EXIF code into a readable value.
				if (data.Length > 0)
					switch(data[0])
					{
						case 1:
							returnValue = "Daylight";
							break;
						case 2:
							returnValue = "Fluorescent";
							break;
						case 3:
							returnValue = "Tungsten (incandescent light)";
							break;
						case 4:
							returnValue = "Flash";
							break;
						case 9:
							returnValue = "Fine weather";
							break;
						case 10:
							returnValue = "Cloudy weather";
							break;
						case 11:
							returnValue = "Shade";
							break;
						case 12:
							returnValue ="Daylight fluorescent (D 5700 - 7100K)";
							break;
						case 13:
							returnValue ="Day white fluorescent (N 4600 - 5400K)";
							break;
						case 14:
							returnValue ="Cool white fluorescent (W 3900 - 4500K)";
							break;
						case 15:
							returnValue ="White fluorescent (WW 3200 - 3700K)";
							break;
						case 17:
							returnValue ="Standard light A";
							break;
						case 18:
							returnValue ="Standard light B";
							break;
						case 19:
							returnValue ="Standard light C";
							break;
						case 20:
							returnValue ="D55";
							break;
						case 21:
							returnValue ="D65";
							break;
						case 22:
							returnValue ="D75.";
							break;
						case 23:
							returnValue ="D50";
							break;
						case 24:
							returnValue ="ISO studio tungsten";
							break;
						case 255:
							returnValue ="other light source";
							break;
						default:
							returnValue = "Reserved";
							break;
					}
				
				return returnValue;		
			} 

			/// <summary>
			/// This method returns the flash EXIF property.
			/// </summary>
			private string Flash()
			{
				//Declare local variables.
				string returnValue = "EXIF property not found.";
				byte[] data = GetPropertyValue(exifCode.Flash);
		
				//Translate the EXIF code into a readable value.
				if (data.Length > 0)
					switch (data[0])
					{
						case 0:
							returnValue = "Flash did not fire.";
							break;
						case 1:
							returnValue = "Flash fired.";
							break;
						case 5:
							returnValue = "Strobe return light not detected.";
							break;
						case 7:
							returnValue = "Strobe return light detected.";
							break;
						case 9:
							returnValue = "Flash fired, compulsory flash mode.";
							break;
						case 13:
							returnValue = "Flash fired, compulsory flash mode, return light not detected.";
							break;
						case 15:
							returnValue = "Flash fired, compulsory flash mode, return light detected.";
							break;
						case 16:
							returnValue = "Flash did not fire, compulsory flash mode.";
							break;
						case 24:
							returnValue = "Flash did not fire, auto mode.";
							break;
						case 25:
							returnValue = "Flash fired, auto mode.";
							break;
						case 29:
							returnValue = "Flash fired, auto mode, return light not detected.";
							break;
						case 31:
							returnValue = "Flash fired, auto mode, return light detected.";
							break;
						case 32:
							returnValue = "No flash function.";
							break;
						case 65:
							returnValue = "Flash fired, red-eye reduction mode.";
							break;
						case 69:
							returnValue = "Flash fired, red-eye reduction mode, return light not detected.";
							break;
						case 71:
							returnValue = "Flash fired, red-eye reduction mode, return light detected.";
							break;
						case 73:
							returnValue = "Flash fired, compulsory flash mode, red-eye reduction mode.";
							break;
						case 77:
							returnValue = "Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected.";
							break;
						case 79:
							returnValue = "Flash fired, compulsory flash mode, red-eye reduction mode, return light detected.";
							break;
						case 89:
							returnValue = "Flash fired, auto mode, red-eye reduction mode.";
							break;
						case 93:
							returnValue = "Flash fired, auto mode, return light not detected, red-eye reduction mode.";
							break;
						case 95:
							returnValue = "Flash fired, auto mode, return light detected, red-eye reduction mode.";
							break;
						default:
							returnValue = "Not defined, reserved.";
							break;
					}
				
				return returnValue;
			} 

			/// <summary>
			/// This method returns the focal length EXIF property.
			/// </summary>
			private string FocalLength()
			{
				//Declare local variables.
				string returnValue = "EXIF property not found."; 
				EXIFRational focalLength = ParsedRational(exifCode.FocalLength);
		
				//Translate the EXIF code into a readable value.
				if (!focalLength.Equals(null))
					if (focalLength.Numerator == 0 && focalLength.Denominator == 0)
					{
						returnValue = "N/A";
					}
					else
					{
						returnValue = string.Format("{0:N0} mm", focalLength.Numerator * 1.0 / focalLength.Denominator);
					}
		
				return returnValue;
			} 

			/// <summary>
			/// This method returns the maker note EXIF property.
			/// </summary>
			private string MakerNote()
			{
				return "Not implemented.";
			} 

			/// <summary>
			/// This method returns the color space EXIF property.
			/// </summary>
			private string ColorSpace()
			{
				//Declare local variables.
				string returnValue = "EXIF property not found.";
				byte[] data = GetPropertyValue(exifCode.ColorSpace);

				//Translate the EXIF code into a readable value.
				if (data.Length > 0)
					switch(data[0])
					{
						case 1:
							returnValue = "sRGB";
							break;
						case 255:
							returnValue ="Uncalibrated";
							break;
						default:
							returnValue = "Reserved";
							break;
					}
				
				return returnValue;		
			} 

			/// <summary>
			/// This method returns the focal plane x resolution EXIF property.
			/// </summary>
			private string FocalPlaneXResolution()
			{
				//Declare local variables.
				string returnValue = "EXIF property not found."; 
				EXIFRational focalPlaneXRes = ParsedRational(exifCode.FocalPlaneXResolution);
		
				//Translate the EXIF code into a readable value.
				if (!focalPlaneXRes.Equals(null))
					returnValue = string.Format("{0:N0} mm", (focalPlaneXRes.Numerator * 1.0 / focalPlaneXRes.Denominator));
		
				return returnValue;
			} 

			/// <summary>
			/// This method returns the focal plane y resolution EXIF property.
			/// </summary>
			private string FocalPlaneYResolution()
			{
				//Declare local variables.
				string returnValue = "EXIF property not found."; 
				EXIFRational focalPlaneYRes = ParsedRational(exifCode.FocalPlaneYResolution);
		
				//Translate the EXIF code into a readable value.
				if (!focalPlaneYRes.Equals(null))
					returnValue = string.Format("{0:N0} mm", focalPlaneYRes.Numerator * 1.0 / focalPlaneYRes.Denominator);
		
				return returnValue;
			} 

			/// <summary>
			/// This method returns the exposure index EXIF property.
			/// </summary>
			private string ExposureIndex()
			{
				//Declare local variables.
				string returnValue = "EXIF property not found."; 
				EXIFRational expIndex = ParsedRational(exifCode.ExposureIndex);
		
				//Translate the EXIF code into a readable value.
				if (!expIndex.Equals(null))
					returnValue = string.Format("{0:N0} mm", expIndex.Numerator * 1.0 / expIndex.Denominator);
		
				return returnValue;
			} 

			/// <summary>
			/// This method returns the sensing method EXIF property.
			/// </summary>
			private string SensingMethod()
			{
				// Declare local variables.
				// Get the value for this EXIF property.
				byte[] data = GetPropertyValue(exifCode.SensingMethod);
				string returnValue = "EXIF property not found.";

				if(data.Length > 0)
					switch(data[0])
					{
						case 1:
							returnValue = "Not defined.";
							break;
						case 2:
							returnValue = "One-chip color area sensor.";
							break;
						case 3:
							returnValue = "Two-chip color area sensor.";
							break;
						case 4:
							returnValue = "Three-chip color area sensor.";
							break;
						case 5:
							returnValue = "Color sequential area sensor.";
							break;					
						case 7:
							returnValue = "Trilinear sensor.";
							break;
						case 8:
							returnValue = "Color sequential linear sensor";
							break;
						default:
							returnValue = "Reserved.";
							break;
					}	

				return returnValue;
			}

			/// <summary>
			/// This method returns the file source EXIF property.
			/// </summary>
			private string FileSource()
			{
				// Declare local variables.
				// Get the value for this EXIF property.
				byte[] data = GetPropertyValue(exifCode.FileSource);
				string returnValue = "EXIF property not found.";

				if(data.Length > 0)
					switch(data[0])
					{
						case 3:
							returnValue = "DSC";
							break;
						default:
							returnValue = "Reserved";
							break;
					}
				
				return returnValue;
			}

			/// <summary>
			/// This method returns the scene type EXIF property.
			/// </summary>
			private string SceneType()
			{
				// Declare local variables.
				// Get the value for this EXIF property.
				byte[] data = GetPropertyValue(exifCode.FileSource);
				string returnValue = "EXIF property not found.";

				if(data.Length > 0)
					switch(data[0])
					{
						case 1:
							returnValue = "A directly photographed image.";
							break;
						default:
							returnValue = "Reserved.";
							break;
					}
				
				return returnValue;
			}

			/// <summary>
			/// This method returns the custom rendered EXIF property.
			/// </summary>
			private string CustomRendered()
			{
				// Declare local variables.
				// Get the value for this EXIF property.
				byte[] data = GetPropertyValue(exifCode.CustomRendered);
				string returnValue = "EXIF property not found.";

				if(data.Length > 0)
					switch(data[0])
					{
						case 0:
							returnValue = "Normal process";
							break;
						case 1:
							returnValue = "Custom process";
							break;
						default:
							returnValue = "Reserved";
							break;
					}
				
				return returnValue;
			}

			/// <summary>
			/// This method returns the exposure mode EXIF property.
			/// </summary>
			private string ExposureMode()
			{
				// Declare local variables.
				// Get the value for this EXIF property.
				byte[] data = GetPropertyValue(exifCode.ExposureMode);
				string returnValue = "EXIF property not found.";

				if(data.Length > 0)
				{
					switch(data[0])
					{
						case 0:
							returnValue =  "Auto exposure";
							break;
						case 1:
							returnValue =  "Manual exposure";
							break;
						case 2:
							returnValue =  "Auto bracket";
							break;
						default:
							returnValue =  "Reserved";
							break;
					}
				}
				
				return returnValue;
			}

			/// <summary>
			/// This method returns the white balance EXIF property.
			/// </summary>
			private string WhiteBalance()
			{
				// Declare local variables.
				// Get the value for this EXIF property.
				byte[] data = GetPropertyValue(exifCode.WhiteBalance);
				string returnValue = "EXIF property not found.";

				if(data.Length > 0)
					switch(data[0])
					{
						case 0:
							returnValue =  "Auto white balance";
							break;
						case 1:
							returnValue =  "Manual white balance";
							break;
						default:
							returnValue =  "Reserved";
							break;
					}

				return returnValue;
			}

			/// <summary>
			/// This method returns the focal length in 35mm film EXIF property.
			/// </summary>
			private string FocalLengthIn35mmFilm()
			{
				// Declare local variables.
				// Get the value for this EXIF property.
				byte[] data = GetPropertyValue(exifCode.FocalLengthIn35mmFilm);
				string returnValue = "EXIF property not found.";

				if(data.Length > 0)
					if(data[0] == 0)
					{
						returnValue =  "Unknown";
					}
					else if (data[0].ToString().Trim() == "NaN")
					{
						returnValue = "N/A";
					}
					else
					{
						returnValue = data[0].ToString() + "mm";
					}
				
				return returnValue;
			}

			/// <summary>
			/// This method returns the scene capture type EXIF property.
			/// </summary>
			private string SceneCaptureType()
			{
				// Declare local variables.
				// Get the value for this EXIF property.
				byte[] data = GetPropertyValue(exifCode.SceneCaptureType);
				string returnValue = "EXIF property not found.";

				if(data.Length > 0)
					switch(data[0])
					{
						case 0:
							returnValue =  "Standard";
							break;
						case 1:
							returnValue =  "Landscape";
							break;
						case 2:
							returnValue =  "Portrait";
							break;
						case 3:
							returnValue =  "Night scene";
							break;
						default:
							returnValue =  "Reserved";
							break;
					}
				
				return returnValue;
			}

			/// <summary>
			/// This method returns the gain control EXIF property.
			/// </summary>
			private string GainControl()
			{
				// Declare local variables.
				// Get the value for this EXIF property.
				byte[] data = GetPropertyValue(exifCode.GainControl);
				string returnValue = "EXIF property not found.";

				if(data.Length > 0)
					switch(data[0])
					{
						case 0:
							returnValue =  "None";
							break;
						case 1:
							returnValue =  "Low gain up";
							break;
						case 2:
							returnValue =  "High gain up";
							break;
						case 3:
							returnValue =  "Low gain down";
							break;
						case 4:
							returnValue =  "High gain down";
							break;
						default:
							returnValue =  "Reserved";
							break;
					}
				
				return returnValue;
			}

			/// <summary>
			/// This method returns the contrast EXIF property.
			/// </summary>
			private string Contrast()
			{
				// Declare local variables.
				// Get the value for this EXIF property.
				byte[] data = GetPropertyValue(exifCode.Contrast);
				string returnValue = "EXIF property not found.";

				if(data.Length > 0)
					switch(data[0])
					{
						case 0:
							returnValue =  "Normal";
							break;
						case 1:
							returnValue =  "Soft";
							break;
						case 2:
							returnValue =  "Hard";
							break;
						default:
							returnValue =  "Reserved";
							break;
					}
				
				return returnValue;
			}

			/// <summary>
			/// This method returns the saturation EXIF property.
			/// </summary>
			private string Saturation()
			{
				// Declare local variables.
				// Get the value for this EXIF property.
				byte[] data = GetPropertyValue(exifCode.Saturation);
				string returnValue = "EXIF property not found.";

				if(data.Length > 0)
					switch(data[0])
					{
						case 0:
							returnValue =  "Normal";
							break;
						case 1:
							returnValue =  "Low saturation";
							break;
						case 2:
							returnValue =  "High saturation";
							break;
						default:
							returnValue =  "Reserved";
							break;
					}
				
				return returnValue;
			}

			/// <summary>
			/// This method returns the sharpness EXIF property.
			/// </summary>
			private string Sharpness()
			{
				// Declare local variables.
				// Get the value for this EXIF property.
				byte[] data = GetPropertyValue(exifCode.Sharpness);
				string returnValue = "EXIF property not found.";

				if(data.Length > 0)
					switch(data[0])
					{
						case 0:
							returnValue = "Normal";
							break;
						case 1:
							returnValue = "Soft";
							break;
						case 2:
							returnValue = "Hard";
							break;
						default:
							returnValue = "Reserved";
							break;
					}
				
				return returnValue;
			}

			/// <summary>
			/// This method returns the subject distance range EXIF property.
			/// </summary>
			private string SubjectDistanceRange()
			{
				// Declare local variables.
				// Get the value for this EXIF property.
				byte[] data = GetPropertyValue(exifCode.SubjectDistanceRange);
				string returnValue = "EXIF property not found.";

				if(data.Length > 0)
					switch(data[0])
					{
						case 0:
							returnValue =  "Unknown";
							break;
						case 1:
							returnValue =  "Macro";
							break;
						case 2:
							returnValue =  "Close view";
							break;
						case 3:
							returnValue =  "Distant view";
							break;
						default:
							returnValue =  "Reserved";
							break;
					}
				
				return returnValue;
			}

			/// <summary>
			/// This method returns the subject location EXIF property.
			/// </summary>
			private string SubjectLocation()
			{
				// Declare local variables.
				// Get the value for this EXIF property.
				byte[] data = GetPropertyValue(exifCode.SubjectLocation);
				string returnValue = "EXIF property not found.";

				if(data.Length > 0)
					returnValue =  "(" + data[0].ToString() + ", " + data[1].ToString() + ")";
				
				return returnValue;
			}

			/// <summary>
			/// This method returns the digital zoom ratio EXIF property.
			/// </summary>
			private string DigitalZoomRatio()
			{
				//Declare local variables.
				string returnValue = "EXIF property not found."; 

				EXIFRational dzr = ParsedRational(exifCode.DigitalZoomRatio);
		
				//Translate the EXIF code into a readable value.
				if (!dzr.Equals(null))
					returnValue = dzr.Numerator.ToString() + ":" + dzr.Denominator.ToString();
		
				return returnValue;
			}

			/// <summary>
			/// This method returns the brightness value EXIF property.
			/// </summary>
			private string BrightnessValue()
			{
				//Declare local variables.
				string returnValue = "EXIF property not found."; 

				EXIFRational data = ParsedRational(exifCode.DigitalZoomRatio);
			
				//Translate the EXIF code into a readable value.
				if (!data.Equals(null))
					if((long)data.Numerator >= Int32.MaxValue)
						returnValue = "Unknown";
					else
						returnValue = Math.Log(data.Numerator/data.Denominator, 2.0).ToString();
			
				return returnValue;
			}

			/// <summary>
			/// This method returns the max aperture value EXIF property.
			/// </summary>
			private string MaxApertureValue()
			{
				//Declare local variables.
				string returnValue = "EXIF property not found."; 

				EXIFRational data = ParsedRational(exifCode.MaxApertureValue);
				
				//Translate the EXIF code into a readable value.
				if (!data.Equals(null))
					returnValue = string.Format("f{0}", (double)(data.Numerator/data.Denominator));
				
				return returnValue;
			}

			/// <summary>
			/// This method returns the exposure bias value EXIF property.
			/// </summary>
			private string ExposureBiasValue()
			{
				//Declare local variables.
				string returnValue = "EXIF property not found."; 

				EXIFRational data = ParsedRational(exifCode.ExposureBiasValue);
					
				//Translate the EXIF code into a readable value.
				if (!data.Equals(null))
					returnValue = string.Format("f{0}", (double)(data.Numerator/data.Denominator));
					
				return returnValue;
			}
		#endregion

		#region -- Private helper functions --
			// Private helper functions.
			/// <summary>
			/// This method retrieves the data from the propery items collection.
			/// </summary>
			private byte[] GetPropertyValue(exifCode exifCode)

			{
				return _picture.GetPropertyItem((int) exifCode).Value;	
			}

			/// <summary>
			/// This method returns string EXIF data.
			/// </summary>
			private string ParsedString(exifCode exifCode)
			{
				// Declare local variables.
				// Retrieve the data for this EXIF property.
				byte[] data = GetPropertyValue(exifCode);

				// Holds the return value.
				string parsed = "";

				// If there's data, go ahead and parse it.
				if (data.Length > 1)
				{
					// Allocate some memory.
					IntPtr h = Marshal.AllocHGlobal(data.Length);

					int i = 0;

					foreach (byte b in data)
						Marshal.WriteByte(h, i++, b);

					parsed = Marshal.PtrToStringAnsi(h);
					Marshal.FreeHGlobal(h);
				}

				return parsed;				
			}
			
			/// <summary>
			/// This method returns rational EXIF data.
			/// </summary>
			private EXIFRational ParsedRational(exifCode exifCode)
			{
					// Declare local variables.
					// Retrieve the data for this EXIF property.
					byte[] data = GetPropertyValue(exifCode);
					
					// Parse the data.
					EXIFRational parsed = new EXIFRational(data);

					return parsed;
			}
			
			/// <summary>
			/// This method returns an array of rational EXIF data.
			/// </summary>
			private EXIFRational[] ParsedRationalArray(exifCode exifCode)
			{
				// Declare local variables.
				// Retrieve the data for this EXIF property.
				byte[] data = GetPropertyValue(exifCode);

				// Holds the return value.
				EXIFRational[] parsed = null;

				int arraySize = (data.Length / 8);

				if (arraySize > 0)
				{
					parsed = new EXIFRational[arraySize];

					for (int i = 0; i < arraySize; i++)
						parsed[i] = new EXIFRational(data, i * 8);
				}

				return parsed;
			}

			/// <summary>
			/// This method returns date/time EXIF data.
			/// </summary>
			private DateTime ParsedDate(exifCode exifCode)
			{
				// Declare local variables.
				// Create a new date object.
				DateTime ret = new DateTime(1900,1,1,0,0,0);

				// Parse the data.
				string date = ParsedString(exifCode);

				// Format the data.
				if (date.Length >= 19)
				{
					int year = int.Parse(date.Substring(0, 4));
					int month = int.Parse(date.Substring(5,2));
					int day = int.Parse(date.Substring(8,2));

					if (year == 1900 && month == 1 && day == 1)
					{
						throw new Exception("EXIF Property not found.");
					}
					else
					{
						int hour = int.Parse(date.Substring(11,2));
						int minute = int.Parse(date.Substring(14,2));
						int second = int.Parse(date.Substring(17,2));
						ret = new DateTime(year, month, day, hour, minute, second);
					}
				}
				else
				{
					throw new Exception("EXIF Property not found.");
				}

				return ret;
			}

			/// <summary>
			/// This method returns the type of resolution used in the image.
			/// </summary>
			private string ParseResolution(exifCode resolutionAxis)
			{
				// Declare local variables.
				string returnValue = "";
				byte[] resUnit = GetPropertyValue(exifCode.ResolutionUnit);
				byte[] res = GetPropertyValue(resolutionAxis);

				if ((resUnit != null) && (res != null))
				{
					EXIFRational resFraction = ParsedRational(resolutionAxis);

					double resValue =  resFraction.Numerator * 1.0 / resFraction.Denominator;

					returnValue = String.Format("{0:N0}", resValue);

					switch (res[0])
					{
						case 2:
							returnValue += " dpi";
							break;
						case 3:
							returnValue += " dpcm";
							break;
						default:
							returnValue += " dpi";
							break;
					}
				}
				
				return returnValue;
			}

			/// <summary>
			/// This method numeric information that does not require additional formatting.
			/// </summary>
			private string UnformattedShort(exifCode exifCode)
			{
				byte[] data = GetPropertyValue(exifCode);

				return data[0].ToString();
			}
		#endregion
		
		#region -- Private helper objects --
			// Private helper objects.

			/// <summary>
			/// This object converts the byte data into rational values used
			/// in determining EXIF property values. 
			/// </summary>
			private struct EXIFRational
			{
				public int Denominator;
				public int Numerator;

				/// <summary>
				/// Creates an EXIFRational object from EXIF byte data
				/// </summary>
				/// <param name="data">Byte data to create from</param>
				public EXIFRational(byte[] data)
				{
					Denominator = 0;
					Numerator = 0;

					if (data.Length >= 8)
					{
						Numerator = data[0];
						Numerator |= (data[1] >> 8);
						Numerator |= (data[2] >> 16);
						Numerator |= (data[3] >> 24);
						Denominator = data[4];
						Denominator |= (data[5] >> 8);
						Denominator |= (data[6] >> 16);
						Denominator |= (data[7] >> 24);
					}
				}

				/// <summary>
				/// Creates an EXIFRational object from EXIF byte data,
				/// starting at the byte specified by ofs
				/// </summary>
				/// <param name="data">EXIF byte data</param>
				/// <param name="ofs">Initial Byte</param>
				public EXIFRational(byte[] data, int ofs)
				{
					Denominator = 0;
					Numerator = 0;

					if (data.Length >= ofs + 8)
					{
						Numerator = data[ofs];
						Numerator |= (data[ofs + 1] >> 8);
						Numerator |= (data[ofs + 2] >> 16);
						Numerator |= (data[ofs + 3] >> 24);
						Denominator = data[ofs + 4];
						Denominator |= (data[ofs + 5] >> 8);
						Denominator |= (data[ofs + 6] >> 16);
						Denominator |= (data[ofs + 7] >> 24);
					}
				}

				/// <summary>
				/// Returns the value of the fraction as a string
				/// </summary>
				/// <returns>The value of the fraction as a string</returns>
				public override string ToString()
				{
					string ret;

					if (this.Denominator == 0)
						ret = "N/A";
					else
						ret = String.Format("{0:F2}", this.Numerator * 1.0/this.Denominator);

					return ret;
				}
			}
		#endregion


         protected int ID
         {
            get{return _ID;}
            set{_ID = value;}
         }

        protected DateTime CreateDate
        {
            get{return _createDate;}
            set{_createDate = value;}
        }

        protected string Name
        {
            get{return _name;}
            set{_name = value;}
        }
     }

        #region enum defination
        /// <summary>
        /// Enumerates the known EXIF codes.
        /// </summary>
        public enum exifCode : int
        {
            InteroperabilityIndex = 1, ImageWidth = 256,ImageLength = 257, BitsPerSample = 258, Compression = 259,
            PhotometricInterpretation = 262, Orientation = 274,SamplesPerPixel = 277, PlanarConfiguration = 284,
            YCbCrSubSampling = 530, YCbCrPositioning = 531, XResolution = 282, YResolution = 283,
            ResolutionUnit = 296, StripOffsets = 273, RowsPerStrip = 278, StripByteCounts = 279,
            JPEGInterchangeFormatLength = 514, TransferFunction = 301, WhitePoint = 318, PrimaryChromaticities = 319,
            YCbCrCoefficients = 529, ReferenceBlackWhite = 532, DateTime = 306, ImageDescription = 270,
            Make = 271, Model = 272,  Software = 305, Artist = 315, Copyright = 33432, ExifVersion = 36864,
            FlashpixVersion = 40960, ColorSpace = 40961, PixelXDimension = 40962, PixelYDimension = 40963,
            ComponentsConfiguration = 37121, CompressedBitsPerPixel = 37122, MakerNote = 37500,
            UserComment = 37510, RelatedSoundFile = 40964, DateTimeOriginal = 36867, DateTimeDigitized = 36868,
            SubsecTime = 37520, SubsecTimeOriginal = 37521, SubsecTimeDigitized = 37522, ExposureTime = 33434,
            FNumber = 33437, ExposureProgram = 34850, SpectralSensitivity = 34852, ISOSpeedRatings = 34855,
            OECF = 34856, ShutterSpeedValue = 37377, ApertureValue = 37378, BrightnessValue = 37379,
            ExposureBiasValue = 37380, MaxApertureValue = 37381, SubjectDistance = 37382,
            MeteringMode = 37383, LightSource = 37384, Flash = 37385, SubjectArea = 37396, FocalLength = 37386,
            FlashEnergy = 41483, SpatialFrequencyResponse = 41484, FocalPlaneXResolution = 41486,
            FocalPlaneYResolution = 41487, FocalPlaneResolutionUnit = 41488, SubjectLocation = 41492,
            ExposureIndex = 41493, SensingMethod = 41495, FileSource = 41728, SceneType = 41729,
            CFAPattern = 41730, CustomRendered = 41985, ExposureMode = 41986, WhiteBalance = 41987,
            DigitalZoomRatio = 41988, FocalLengthIn35mmFilm = 41989, SceneCaptureType = 41990,
            GainControl = 41991, Contrast = 41992, Saturation = 41993, Sharpness = 41994,
            DeviceSettingDescription = 41995, SubjectDistanceRange = 41996, ImageUniqueID = 42016
        }
        #endregion   
}